// --------------------------------------------------------------------
// TCP服务端实现
// --------------------------------------------------------------------

#include "tserver.hpp"
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#incldue <sys/select.h>

namespace ymbxSock
{

    tcpSrv::tcpSrv(uint16_t port) : _port(port)
    {
        CreateLog("tcpserver");
        _sock.Socket("tcp");
        _sock.Bind("", _port);
        _sock.Listen();
#if __cplusplus < 201103L
        pthread_mutex_init(&_conn_mtx, nullptr);
#endif
        _conns = std::make_shared<std::unordered_map<int, connSock>>();
        // LOG_INFO("tcpserver", "tcp服务器开始监听");
        _defaulthandler=[](const std::string& mes)->std::string
        {
            return "echo:"+mes;
        };
    }
#if __cplusplus >= 201103L
    std::string tcpSrv::parseReq(const std::string& req,std::string* taskData){
        //请求格式为：TASK:calculate:data
        if(req.size()<5){
            *taskData=req;
            return "";
        }
        if(req.substr(0,5)=="TASK:"){
            size_t pos=req.find(":",5);
            if(pos!=std::string::npos){
                std::string tn=req.substr(5,pos-5);
                *taskData=req.substr(pos+1);
                return tn;
            }
        }
        *taskData=req;
        return "";
    }
        
    void tcpSrv::addTask(const std::string& taskname,TaskHandler taskhandler){
        std::lock_guard<std::mutex> lock(_task_mtx);
        _tasks[taskname]=taskhandler;
    }
    void tcpSrv::removeTask(const std::string& taskname){
        std::lock_guard<std::mutex> lock(_task_mtx);
        auto it=_tasks.find(taskname);
        if(it!=_tasks.end()){
            _tasks.erase(it);
        }
    }
    void tcpSrv::handlerClient(int sock, const std::string &ip, uint16_t port)
    {
        std::string mes;
        while (1)
        {
            char buffer[1024];
            memset(buffer, 0, sizeof(buffer));
            int rsize = recv(sock, buffer, sizeof(buffer) - 1, 0);
            if (rsize < 0)
            {
                LOG_ERROR("tcpserver", "接收数据失败：", strerror(errno));
                (*_conns)[sock].status = false;
                break;
            }
            else if (rsize == 0)
            {
                LOG_INFO("tcpserver", ip, ":", port, ">>>连接关闭");
                (*_conns)[sock].status = false;
                break;
            }
            mes.assign(buffer, rsize);
            std::cout << "接收到来自" << ip << ":" << port << "的消息>>>" << mes << std::endl;
            sleep(1);
            // 业务处理
            std::string resp = processTask(mes);
            send(sock, resp.c_str(), resp.size(), 0);
        }
        (*_conns)[sock].status = false;
        close(sock);
    }
    std::string tcpSrv::processTask(const std::string &req)
    {
        std::string taskdata;
        std::string tn=parseReq(req,&taskdata);
        if(tn.empty()){
            return _defaulthandler(taskdata);
        }else{
            auto it=_tasks.find(tn);
            if(it!=_tasks.end()){
                return it->second(taskdata);
            }else{
                return "unkown taskname:"+tn;
            }
        }
    }
#endif

#if __cplusplus < 201103L
    void tcpSrv::Start(const Handler &handler)
    {
        std::cout << "server start>>>\n";
        while (1)
        {
            std::string ip;
            uint16_t port;
            int ret = _sock.Accept(&ip, &port);
            
            pthread_mutex_lock(&_conn_mtx);
            auto it = _conns->find(ret);
            if (it != _conns->end() && (*_conns)[ret].status == true)
            {
                LOG_ERROR("tcpserver", "该socket正在使用中");
            }
            else
            {
                (*_conns)[ret] = {ret, ip, port, true};
                LOG_INFO("tcpserver", "接收连接成功,开始放入线程池中处理");
                _tpools.pushPool(threadWork(ret, handler, _conns));
            }
            pthread_mutex_unlock(&_conn_mtx);
        }
    }
#else
    void tcpSrv::Start()
    {
        std::cout << "server start>>>\n";
        while (1)
        {
            std::string ip;
            uint16_t port;
            int ret = _sock.Accept(&ip, &port);
            std::unique_lock<std::mutex> lock(_conn_mtx);
            auto it = _conns->find(ret);
            if (it != _conns->end() && (*_conns)[ret].status == true)
            {
                LOG_ERROR("tcpserver", "该socket正在使用中");
            }
            else
            {
                (*_conns)[ret] = {ret, ip, port, true};
                // LOG_INFO("tcpserver", "接收连接成功,开始放入线程池中处理");
                _tpools.pushPool([this, ret, ip, port]
                                 { this->handlerClient(ret, ip, port); });
            }
        }
    }
#endif
        tcpSrv::~tcpSrv()
        {
            _sock.Close();
#if __cplusplus < 201103L
            pthread_mutex_destroy(&_conn_mtx);
#endif
        }
#if __cplusplus < 201103L
        threadWork::threadWork(int csock, const Handler &handler, std::shared_ptr<std::unordered_map<int, connSock>> conns) : _csock(csock), _handler(handler), _conns(conns) {}
        void threadWork::operator()()
        {
            std::string mes;
            while (1)
            {
                char buffer[1024];
                memset(buffer, 0, sizeof(buffer));
                std::string ip = (*_conns)[_csock].ip;
                uint16_t port = (*_conns)[_csock].port;
                int ret = recv(_csock, buffer, sizeof(buffer) - 1, 0);
                if (ret < 0)
                {
                    LOG_ERROR("tcpserver", "接收数据失败：", strerror(errno));
                    (*_conns)[_csock].status = false;
                    break;
                }
                else if (ret == 0)
                {
                    LOG_INFO("tcpserver", ip, ":", port, ">>>连接关闭");
                    (*_conns)[_csock].status = false;
                    break;
                }
                mes.assign(buffer, ret);
                std::cout << "接收到来自" << ip << ":" << port << "的消息>>>" << mes << std::endl;
                sleep(1);
                std::string resp;
                // 业务处理
                _handler(mes, &resp);
                send(_csock, resp.c_str(), resp.size(), 0);
            }
            (*_conns)[_csock].status = false;
            close(_csock);
        }
#endif
    }
#if __cplusplus < 201103L
    void working(const std::string &req, std::string *resp)
    {
        *resp = req;
    }
#else
    std::string Print(const std::string& mes){
        std::cout<<mes<<std::endl;
        return mes;
    }
    std::string Cal(const std::string& mes){
        size_t pos=mes.find('+');
        if(pos!=std::string::npos){
            // std::string a=mes.substr(0,pos);
            // std::string b=mes.substr(pos+1);
            int a=std::atoi(mes.substr(0,pos).c_str());
            int b=std::atoi(mes.substr(pos+1).c_str());
            return std::to_string(a+b);
        }
        return "error expression";
    }
#endif
    int main(int argc, char *argv[])
    {
        if (argc != 2)
        {
            ymbxSock::SrvPromote();
            abort();
        }
        uint16_t port = std::atoi(argv[1]);
        ymbxSock::tcpSrv srv(port);
#if __cplusplus >= 201103L
        srv.addTask("print",Print);
        srv.addTask("calulate",Cal);
        srv.Start();
#else
        srv.Start(working);
#endif
        
        return 0;
    }